<template>
  <a-spin :loading="loading" style="width: 100%">
    <a-card class="general-card" title="数据总览">
      <a-row justify="space-between">
        <a-col v-for="(item, idx) in renderData" :key="idx" :span="6">
          <a-statistic
            :title="item.title"
            :value="item.value"
            show-group-separator
            :value-from="0"
            animation
          >
            <template #prefix>
              <span class="statistic-prefix" :style="{ background: item.prefix.background }">
                <component :is="item.prefix.icon" :style="{ color: item.prefix.iconColor }"/>
              </span>
            </template>
          </a-statistic>
        </a-col>
      </a-row>
      <Chart style="height: 328px; margin-top: 20px" :option="chartOption" />
    </a-card>
  </a-spin>
</template>

<script lang="ts" setup>
  import { computed, ref } from 'vue';
  import { useI18n } from 'vue-i18n';
  import { LineSeriesOption } from 'echarts';

  import useLoading from '@/hooks/loading';
  import useThemes from '@/hooks/themes';
  import useChartOption from '@/hooks/chart-option';
  import { ToolTipFormatterParams } from '@/types/echarts';
  import { AnyObject } from '@/types/global';
  import { apiOverview } from '@/api/dashboard';

  const { loading, setLoading } = useLoading(true);
  const { t } = useI18n();
  const { isDark } = useThemes();
  // 提示框浮层内容格式器
  const tooltipItemsHtmlString = (items: ToolTipFormatterParams[]) => {
    return items
      .map(
        (el) => `<div class="content-panel">
          <p>
            <span style="background-color: ${el.color}" class="tooltip-item-icon"></span><span>${el.seriesName}</span>
          </p>
          <span class="tooltip-value">${el.value.toLocaleString()}</span>
        </div>`
      )
      .reverse()
      .join('');
  };
  // 图表配置
  const generateSeries = (
    name: string,
    itemColor: string,
    itemBorderColor: string,
    data: number[],
    seriesType: any,
    yAxisIndex: number,
    smooth: boolean,
    lineStyleType: any,
  ): LineSeriesOption => {
    return {
      name,
      data,
      // stack: 'Total',
      type: seriesType,
      yAxisIndex, // 使用的 y 轴的 index，在单个图表实例中存在多个 y轴的时候有用
      smooth, // 是否平滑曲线显示
      symbol: 'circle', // 标记的图形
      symbolSize: 10, // 标记的大小
      showSymbol: true, // 是否显示 symbol, 如果 false 则只有在 tooltip hover 的时候显示
      // 折线拐点标志的样式
      itemStyle: {
        color: itemColor,
      },
      // 折线图的高亮状态
      emphasis: {
        focus: 'series',
        itemStyle: {
          color: itemColor,
          borderWidth: 2,
          borderColor: itemBorderColor,
        },
      },
      // 线条样式
      lineStyle: {
        width: 2,
        type: lineStyleType, // solid：实线，dotted：点型虚线，dashed：线性虚线
        color: itemColor,
      },
      // 区域填充样式。设置后显示成区域面积图
      areaStyle: {
        opacity: 0.1,
        color: itemColor,
      },
    };
  };
  function graphicFactory(side: AnyObject) {
    return {
      type: 'text',
      bottom: '8',
      ...side,
      style: {
        text: '',
        textAlign: 'center',
        fill: '#4E5969',
        fontSize: 12,
      },
    };
  }
  const graphicElements = ref([
    graphicFactory({ left: '2.6%' }),
    graphicFactory({ right: 0 }),
  ]);

  const renderData = computed(() => [
    {
      title: '会员数',
      value: 1275,
      prefix: {
        icon: 'icon-user',
        background: isDark.value ? '#3F385E' : '#F5E8FF',
        iconColor: isDark.value ? '#8558D3' : '#722ED1',
      },
    },
    {
      title: '文章数',
      value: 1902,
      prefix: {
        icon: 'icon-book',
        background: isDark.value ? '#593E2F' : '#FFE4BA',
        iconColor: isDark.value ? '#F29A43' : '#F77234',
      },
    },
    {
      title: '点击量',
      value: 2445,
      prefix: {
        icon: 'icon-thumb-up',
        background: isDark.value ? '#3D5A62' : '#E8FFFB',
        iconColor: isDark.value ? '#6ED1CE' : '#33D1C9',
      },
    },
    {
      title: '分享量',
      value: 3034,
      prefix: {
        icon: 'icon-share-alt',
        background: isDark.value ? '#354276' : '#E8F3FF',
        iconColor: isDark.value ? '#4A7FF7' : '#165DFF',
      },
    },
  ]);
  const xAxis = ref<string[]>([]); // 天
  const memberData = ref<number[]>([]);
  const articleData = ref<number[]>([]);
  const clickData = ref<number[]>([]);
  const shareData = ref<number[]>([]);
  const { chartOption } = useChartOption((dark) => {
    return {
      // 直角坐标系内绘图网格
      grid: {
        left: '6%',
        right: '6%',
        top: '40',
        bottom: '30',
      },
      // 图例组件展现了不同系列的标记(symbol)，颜色和名字。可以通过点击图例控制哪些系列不显示。
      legend: {
        icon: 'circle',
        textStyle: {
          color: '#4E5969',
        },
        selected: {
          '会员数': true,
          '文章数': true,
          '点击量': true,
          '分享量': false,
        },
      },
      // 直角坐标系 grid 中的 x 轴
      xAxis: {
        type: 'category',
        offset: 2,
        data: xAxis.value,
        boundaryGap: false, // 坐标轴两边留白策略
        // 坐标轴刻度标签的相关设置
        axisLabel: {
          color: '#4E5969',
          // 刻度标签的内容格式器【使用函数模板，函数参数分别为刻度数值（类目），刻度的索引】
          formatter(value: number, idx: number) {
            // 去掉两次，配合 graphic 一起使用
            if (idx === 0) {
              return '';
            }
            if (idx === xAxis.value.length - 1) {
              return '';
            }
            return `${value}`;
          },
        },
        axisLine: {
          show: false, // 是否显示坐标轴轴线
        },
        axisTick: {
          show: false, // 是否显示坐标轴刻度
        },
        splitLine: {
          show: false, // 是否显示分隔线。默认数值轴显示，类目轴不显示
        },
        // 坐标轴指示器配置项
        axisPointer: {
          show: true,
          lineStyle: {
            color: '#23ADFF',
            width: 2,
          },
        },
      },
      // 直角坐标系 grid 中的 y 轴
      yAxis: [
        {
          type: 'value',
          name: '数量', // 坐标轴名称
          // splitNumber: 5, // 坐标轴的分割段数
          // interval: '',
          axisLine: {
            show: true, // 是否显示坐标轴轴线
          },
          // 坐标轴刻度标签的相关设置
          axisLabel: {
            formatter(value: number, idx: number) {
              if (idx === 0) {
                return String(value);
              }
              return `${value / 1000}k`;
            },
          },
          // 坐标轴在 grid 区域中的分隔线
          splitLine: {
            lineStyle: {
              color: dark ? '#2E2E30' : '#F2F3F5',
            },
          },
        },
        {
          type: 'value',
          name: '数量2',
          axisLine: {
            show: true,
          },
          axisLabel: {
            formatter(value: number, idx: number) {
              return `${value}`;
            },
          },
          splitLine: {
            lineStyle: {
              color: dark ? '#2E2E30' : '#F2F3F5',
            },
          },
        },
      ],
      // 提示框组件
      tooltip: {
        trigger: 'axis',
        // 提示框浮层内容格式器
        formatter(params) {
          const [firstElement] = params as ToolTipFormatterParams[];
          return `<div>
            <p class="tooltip-title">${firstElement.axisValueLabel}</p>
            ${tooltipItemsHtmlString(params as ToolTipFormatterParams[])}
          </div>`;
        },
        className: 'echarts-tooltip-diy',
      },
      // graphic 是原生图形元素组件
      graphic: {
        // 里面是所有图形元素的集合
        elements: graphicElements.value,
      },
      series: [
        generateSeries(
          '会员数',
          '#722ED1',
          '#F5E8FF',
          memberData.value,
          'bar',
          0,
          true,
          'solid',
        ),
        generateSeries(
          '文章数',
          '#F77234',
          '#FFE4BA',
          articleData.value,
          'bar',
          0,
          true,
          'solid',
        ),
        generateSeries(
          '点击量',
          '#33D1C9',
          '#E8FFFB',
          clickData.value,
          'line',
          1,
          false,
          'dashed',
        ),
        generateSeries(
          '分享量',
          '#3469FF',
          '#E8F3FF',
          shareData.value,
          'line',
          1,
          false,
          'dashed',
        ),
      ],
    };
  });

  const fetchData = async () => {
    setLoading(true);
    try {
      const { data } = await apiOverview();
      xAxis.value = data.days;
      memberData.value = data.members;
      articleData.value = data.articles;
      clickData.value = data.clicks;
      shareData.value = data.shares;

      graphicElements.value[0].style.text = data.days[0] as string;
      graphicElements.value[1].style.text = data.days[data.days.length - 1] as string;
    } catch (err) {
      // you can report use errorHandler or other
    } finally {
      setLoading(false);
    }
  };
  fetchData();
</script>

<style scoped lang="less">
  :deep(.arco-statistic) {
    .arco-statistic-title {
      color: rgb(var(--gray-10));
      font-weight: bold;
    }
    .arco-statistic-value {
      display: flex;
      align-items: center;
    }
  }
  .statistic-prefix {
    display: inline-block;
    width: 32px;
    height: 32px;
    margin-right: 8px;
    color: var(--color-white);
    font-size: 16px;
    line-height: 32px;
    text-align: center;
    vertical-align: middle;
    border-radius: 6px;
  }
</style>
